package form_controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	cons2 "shimmer/neusoft_club_backend/controllers/cons"
	"shimmer/neusoft_club_backend/controllers/form_controller/status"
	"shimmer/neusoft_club_backend/controllers/utils"
	"shimmer/neusoft_club_backend/dao/domain"
	"shimmer/neusoft_club_backend/middlewares/auth_middleware"
	"shimmer/neusoft_club_backend/services"
	"shimmer/neusoft_club_backend/services/club_service"
	"shimmer/neusoft_club_backend/services/errs"
	"shimmer/neusoft_club_backend/services/form_service"
)

type postFormMutation struct {
	Content map[string]interface{} `json:"content" xml:"content" form:"content" binding:"required"`
}
type postFormRes struct {
	FormTitle string                        `json:"form_title"`
	Status    *domain.ClubFormStatusFlowDTO `json:"status"`
}

// @Summary 提交申请表单
// @Description
// @Tags 表单
// @Param formID path integer true "表单ID"
// @Param value body  form_controller.postFormMutation true "内容"
// @Success 200 {object} form_controller.postFormRes
// @Router /api/form/{formID} [post]
func postForm(c *gin.Context) {
	user, err := domain.GetUserFromContext(c)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	mutation := &postFormMutation{}
	if err = c.ShouldBind(mutation); err != nil {
		services.AbortWithError(c, err)
		return
	}
	uriParam := &cons2.FormUriParamBinding{}
	if err = c.ShouldBindUri(uriParam); err != nil {
		services.AbortWithError(c, err)
		return
	}
	form, err := form_service.FindFormById(uriParam.FormID)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	// TODO 简化调用
	if form.Type != 0 {
		in, err := club_service.CheckInClub(user.ID, *form.ClubID)
		if err != nil {
			services.AbortWithError(c, err)
			return
		}
		if !in {
			services.AbortWithError(c, errs.ErrIsNotClubMember)
			return
		}
	}
	form, application, err := form_service.PostForm(user.ID, uriParam.FormID, &mutation.Content)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	formStatus := &domain.ClubFormStatusFlowDTO{}
	formStatus.FromStatus(application.Status)

	c.JSON(http.StatusOK, postFormRes{
		FormTitle: form.Title,
		Status:    formStatus,
	})

}

// @Summary 查找表单
// @Description
// @Tags 表单
// @Param formID path integer true "表单ID"
// @Success 200 {object} domain.ClubFormDTO
// @Router /api/form/{formID} [get]
func findFormById(c *gin.Context) {
	uriParam := &cons2.FormUriParamBinding{}
	if err := c.ShouldBindUri(uriParam); err != nil {
		services.AbortWithError(c, err)
		return
	}
	form, err := form_service.FindFormById(uriParam.FormID)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	if form.Type == domain.ClubFormTypeFresh {
		c.JSON(http.StatusOK, form)
		return
	}
	if form.ClubID == nil {
		services.AbortWithError(c, errs.ErrFormIsOrphan)
		return
	}
	user, err := domain.GetUserFromContext(c)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	in, err := club_service.CheckInClub(user.ID, *form.ClubID)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	if !in {
		services.AbortWithError(c, errs.ErrIsNotClubMember)
		return
	}
	c.JSON(http.StatusOK, form)
}

// @Summary 查找用户对于此表单的所有提交
// @Description
// @Tags 表单
// @Param formID path integer true "表单ID"
// @Success 200 {object} []domain.UserApplicationDTO
// @Router /api/form/{formID}/application [get]
func findUsersApplicationForForm(c *gin.Context) {
	user, err := domain.GetUserFromContext(c)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	uriParam := &cons2.FormUriParamBinding{}
	if err = c.ShouldBindUri(uriParam); err != nil {
		services.AbortWithError(c, err)
		return
	}
	pageQuery, err := utils.GetPaginationFromContext(c)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	applications, err := form_service.FindUsersApplicationForForm(user.ID, uriParam.FormID, pageQuery)
	if err != nil {
		services.AbortWithError(c, err)
		return
	}
	c.JSON(http.StatusOK, applications)
}
func ConfigureFormController(r *gin.RouterGroup) {
	{
		statusGroup := r.Group(fmt.Sprintf("/:%s/status", cons2.FormUriParam))
		status.ConfigureFormStatusController(statusGroup)
	}
	r.POST(fmt.Sprintf("/:%s", cons2.FormUriParam), auth_middleware.AuthLoginMiddleware(), postForm)
	r.GET(fmt.Sprintf("/:%s", cons2.FormUriParam), auth_middleware.AuthUserMiddleware(false), findFormById)
	r.GET(fmt.Sprintf("/:%s/application", cons2.FormUriParam), auth_middleware.AuthLoginMiddleware(), findUsersApplicationForForm)

}
